package com.ruoyi.system.service.impl;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.ruoyi.system.domain.SysUser;
import com.ruoyi.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.Ztree;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysDept;
import com.ruoyi.system.domain.SysRole;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.service.ISysDeptService;

/**
 * 部门管理 服务实现
 *
 * @author ruoyi
 */
@Service
public class SysDeptServiceImpl implements ISysDeptService
{
    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 查询部门管理数据
     *
     * @param dept 部门信息
     * @return 部门信息集合
     */
    @Override
    @DataScope(deptAlias = "d")
    public List<SysDept> selectDeptList(SysDept dept)
    {
        return deptMapper.selectDeptList(dept);
    }

    /**
     * 查询部门管理数据build(srm业务前端)
     *
     * @param dept 部门信息
     * @return 部门信息集合
     */
    @Override
//    @DataScope(deptAlias = "d")
    public List<SysDept> selectDeptListBuild(SysDept dept)
    {
    	List<SysDept> depts = deptMapper.selectDeptListBuild(dept);
        return getChildPerms(depts, 0);
    }

    @Override
    public List<SysDept> selectDeptListBuildNew(String username) {
//        List<SysDept> deptlist = deptMapper.selectDeptListBuild(new SysDept());
//        List<SysDept> userlist = deptMapper.selectUserinfoByUsername(username);
//        userlist.forEach(ul -> {
//            ul.setDeptId(-1l);
//            ul.setOrderNum("0");
//        });
//        deptlist.addAll(userlist);
//        return getChildPermsNew(deptlist,0);
        List<SysDept> deptlists = deptMapper.selectDeptListBuild(new SysDept());
//        List<SysDept> deptlist = deptlists.stream().filter(d -> !d.getId().equals(140l)).collect(Collectors.toList());
        List<SysDept> deptlist = deptlists.stream().filter(d -> !d.getId().equals(2l)).collect(Collectors.toList());
//        List<SysDept> depts = deptlist.stream().filter(d -> d.getId().equals(100l)).collect(Collectors.toList()); //取出顶级菜单
        List<SysDept> depts = deptlist.stream().filter(d -> d.getId().equals(1l)).collect(Collectors.toList()); //取出顶级菜单
        List<SysDept> userlist0 = deptMapper.selectUserinfoByUsername(username);
        List<SysDept> userlist = userlist0.stream().filter(u -> u.getParentId() != null).collect(Collectors.toList());//去除没有部门的人员
        if(userlist.size()==0){
            return null;
        }
        userlist.forEach(ul -> {
            ul.setDeptId(-1l);
            ul.setOrderNum("0");
        });
        deptlist.addAll(userlist);
        List<SysDept> hassonlist = new ArrayList<>();
        recursionFnReverse(deptlist,userlist,hassonlist);
        depts.addAll(hassonlist);
        return getChildPerms(depts,0);
    }


    public List<SysDept> selectDeptListBuildEmail(String username) {
//        List<SysDept> deptlist = deptMapper.selectDeptListBuild(new SysDept());
//        List<SysDept> userlist = deptMapper.selectUserinfoByUsername(username);
//        userlist.forEach(ul -> {
//            ul.setDeptId(-1l);
//            ul.setOrderNum("0");
//        });
//        deptlist.addAll(userlist);
//        return getChildPermsNew(deptlist,0);
        SysDept sysDept = new SysDept();
        sysDept.setStatus("0");
        List<SysDept> deptlists = deptMapper.selectDeptListBuild(sysDept);
//        List<SysDept> deptlist = deptlists.stream().filter(d -> !d.getId().equals(140l)).collect(Collectors.toList());
        List<SysDept> deptlist = deptlists.stream().filter(d -> !d.getId().equals(2l)).collect(Collectors.toList());
//        List<SysDept> depts = deptlist.stream().filter(d -> d.getId().equals(100l)).collect(Collectors.toList()); //取出顶级菜单
        List<SysDept> depts = deptlist.stream().filter(d -> d.getId().equals(1l)).collect(Collectors.toList()); //取出顶级菜单
        List<SysDept> userlist0 = deptMapper.selectAllUserinfo();
        List<SysDept> userlist = userlist0.stream().filter(u -> u.getParentId() != null).collect(Collectors.toList());//去除没有部门的人员
        if(userlist.size()==0){
            return null;
        }
        userlist.forEach(ul -> {
            ul.setDeptId(-1l);
            ul.setOrderNum("0");
        });
//        deptlist.addAll(userlist);
        List<SysDept> hassonlist = new ArrayList<>();
        recursionFnReverse(deptlist,userlist,hassonlist);
        depts.addAll(hassonlist);
        List<SysDept> childPerms = getChildPerms(depts, 0);
        return childPerms;
//        return getChildPerms(depts,0);
    }

    @Override
    public List<SysDept> selectDeptListBuildVerify(String username,boolean ifemail) {
//        List<SysDept> deptlist = deptMapper.selectDeptListBuild(new SysDept());
//        List<SysDept> userlist = deptMapper.selectUserinfoByUsername(username);
//        userlist.forEach(ul -> {
//            ul.setDeptId(-1l);
//            ul.setOrderNum("0");
//        });
//        deptlist.addAll(userlist);
//        return getChildPermsNew(deptlist,0);
        SysDept sysDept = new SysDept();
        if(ifemail==true){
            sysDept.setStatus("0");
        }
        List<SysDept> deptlists = deptMapper.selectDeptListBuild(sysDept);
//        List<SysDept> deptlist = deptlists.stream().filter(d -> !d.getId().equals(140l)).collect(Collectors.toList());
        List<SysDept> deptlist = deptlists.stream().filter(d -> !d.getId().equals(2l)).collect(Collectors.toList());
//        List<SysDept> depts = deptlist.stream().filter(d -> d.getId().equals(100l)).collect(Collectors.toList()); //取出顶级菜单
        List<SysDept> depts = deptlist.stream().filter(d -> d.getId().equals(1l)).collect(Collectors.toList()); //取出顶级菜单
        List<SysDept> userlist0 = deptMapper.selectVerifyUserinfoByUsername(username);
        List<SysDept> userlist = userlist0.stream().map(ul -> { //把没有部门的人员放到‘其他’,并将姓名改成 姓名-工号-擅长范围 形式
            if (ul.getParentId() == null) {
                ul.setParentId(422l);
            }
            if(StringUtils.isEmpty(ul.getGoodrange())){
                ul.setGoodrange("无");
            }
            ul.setDeptName(ul.getDeptName()+"-"+ul.getJobnumber()+"-"+ul.getGoodrange());
            return ul;
        }).collect(Collectors.toList());

        if(userlist.size()==0){
            return null;
        }
        userlist.forEach(ul -> {
            ul.setDeptId(-1l);
            ul.setOrderNum("0");
        });
        deptlist.addAll(userlist);
        List<SysDept> hassonlist = new ArrayList<>();
        recursionFnReverse(deptlist,userlist,hassonlist);
        depts.addAll(hassonlist);
        return getChildPerms(depts,0);
    }

    /**
     * 查询部门管理树
     *
     * @param dept 部门信息
     * @return 所有部门信息
     */
    @Override
    @DataScope(deptAlias = "d")
    public List<Ztree> selectDeptTree(SysDept dept)
    {
        List<SysDept> deptList = deptMapper.selectDeptList(dept);
        List<Ztree> ztrees = initZtree(deptList);
        return ztrees;
    }

    /**
     * 根据角色ID查询部门（数据权限）
     *
     * @param role 角色对象
     * @return 部门列表（数据权限）
     */
    @Override
    public List<Ztree> roleDeptTreeData(SysRole role)
    {
        Long roleId = role.getRoleId();
        List<Ztree> ztrees = new ArrayList<Ztree>();
        List<SysDept> deptList = selectDeptList(new SysDept());
        if (StringUtils.isNotNull(roleId))
        {
            List<String> roleDeptList = deptMapper.selectRoleDeptTree(roleId);
            ztrees = initZtree(deptList, roleDeptList);
        }
        else
        {
            ztrees = initZtree(deptList);
        }
        return ztrees;
    }

    /**
     * 对象转部门树
     *
     * @param deptList 部门列表
     * @return 树结构列表
     */
    public List<Ztree> initZtree(List<SysDept> deptList)
    {
        return initZtree(deptList, null);
    }

    /**
     * 对象转部门树
     *
     * @param deptList 部门列表
     * @param roleDeptList 角色已存在菜单列表
     * @return 树结构列表
     */
    public List<Ztree> initZtree(List<SysDept> deptList, List<String> roleDeptList)
    {

        List<Ztree> ztrees = new ArrayList<Ztree>();
        boolean isCheck = StringUtils.isNotNull(roleDeptList);
        for (SysDept dept : deptList)
        {
            if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()))
            {
                Ztree ztree = new Ztree();
                ztree.setId(dept.getDeptId());
                ztree.setpId(dept.getParentId());
                ztree.setName(dept.getDeptName());
                ztree.setTitle(dept.getDeptName());
                if (isCheck)
                {
                    ztree.setChecked(roleDeptList.contains(dept.getDeptId() + dept.getDeptName()));
                }
                ztrees.add(ztree);
            }
        }
        return ztrees;
    }

    /**
     * 查询部门人数
     *
     * @param parentId 部门ID
     * @return 结果
     */
    @Override
    public int selectDeptCount(Long parentId)
    {
        SysDept dept = new SysDept();
        dept.setParentId(parentId);
        return deptMapper.selectDeptCount(dept);
    }

    /**
     * 查询部门是否存在用户
     *
     * @param deptId 部门ID
     * @return 结果 true 存在 false 不存在
     */
    @Override
    public boolean checkDeptExistUser(Long deptId)
    {
        int result = deptMapper.checkDeptExistUser(deptId);
        return result > 0 ? true : false;
    }

    /**
     * 删除部门管理信息
     *
     * @param deptId 部门ID
     * @return 结果
     */
    @Override
    public int deleteDeptById(Long deptId)
    {
        return deptMapper.deleteDeptById(deptId);
    }

    /**
     * 新增保存部门信息
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public int insertDept(SysDept dept)
    {
        if(dept.getParentId()>0) {

            SysDept info = deptMapper.selectDeptById(dept.getParentId());
            // 如果父节点不为"正常"状态,则不允许新增子节点
            if (!UserConstants.DEPT_NORMAL.equals(info.getStatus()))
            {
                throw new BusinessException("部门停用，不允许新增");
            }
            dept.setAncestors(info.getAncestors() + "," + dept.getParentId());
        }
        return deptMapper.insertDept(dept);
    }

    /**
     * 修改保存部门信息
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateDept(SysDept dept)
    {

        SysDept newParentDept = deptMapper.selectDeptById(dept.getParentId());
        SysDept oldDept = selectDeptById(dept.getDeptId());
        if (StringUtils.isNotNull(newParentDept) && StringUtils.isNotNull(oldDept))
        {
        	String ancestors = newParentDept.getAncestors();
        	if (ancestors.startsWith(","))
        	 {
        		ancestors = ancestors.replaceFirst(",","");
        	 }
            String newAncestors = ancestors + "," + newParentDept.getDeptId();
            String oldAncestors = oldDept.getAncestors();
            dept.setAncestors(newAncestors);
            updateDeptChildren(dept.getDeptId(), newAncestors,oldAncestors);
        }
        int result = deptMapper.updateDept(dept);
        if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()))
        {
            // 如果该部门是启用状态，则启用该部门的所有上级部门
            updateParentDeptStatus(dept);
        }
        return result;
    }

    /**
     * 修改该部门的父级部门状态
     *
     * @param dept 当前部门
     */
    private void updateParentDeptStatus(SysDept dept)
    {
        String updateBy = dept.getUpdateBy();
        dept = deptMapper.selectDeptById(dept.getDeptId());
        dept.setUpdateBy(updateBy);
        deptMapper.updateDeptStatus(dept);
    }

    /**
     * 修改子元素关系
     * @param deptId 被修改的部门ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateDeptChildren(Long deptId, String newAncestors,String oldAncestors)
    {
        List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
        for (SysDept child : children)
        {
            child.setAncestors(child.getAncestors().replace(oldAncestors,newAncestors));
        }
        if (children.size() > 0)
        {
            deptMapper.updateDeptChildren(children);
        }
    }

    /**
     * 根据部门ID查询信息
     *
     * @param deptId 部门ID
     * @return 部门信息
     */
    @Override
    public SysDept selectDeptById(Long deptId)
    {
        return deptMapper.selectDeptById(deptId);
    }

    /**
     * 根据部门ID查询信息(批量)
     *
     * @param  部门ID
     * @return 部门信息
     */
    @Override
    public List<SysDept> selectDeptByIdlist(String deptIdlist)
    {
    	//sql中使用${}，需检查参数是否含字母，防止sql注入
    	if (StringUtils.isNotEmpty(deptIdlist) && deptIdlist != null && judgeContainsStr(deptIdlist))
    	{
    		deptIdlist = null;
    	}
        return deptMapper.selectDeptByIdlist(deptIdlist);
    }


    /**
     * 使用正则表达式来判断字符串中是否包含字母
     * @param str 待检验的字符串
     * @return 返回是否包含
     * true: 包含字母 ;false 不包含字母
     */
    public boolean judgeContainsStr(String str) {
        String regex=".*[a-zA-Z]+.*";
        Matcher m=Pattern.compile(regex).matcher(str);
        return m.matches();
    }

    /**
     * 校验部门名称是否唯一
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public String checkDeptNameUnique(SysDept dept)
    {
        Long deptId = StringUtils.isNull(dept.getDeptId()) ? -1L : dept.getDeptId();
        SysDept info = deptMapper.checkDeptNameUnique(dept.getDeptName(), dept.getParentId());
        if (StringUtils.isNotNull(info) && info.getDeptId().longValue() != deptId.longValue())
        {
            return UserConstants.DEPT_NAME_NOT_UNIQUE;
        }
        return UserConstants.DEPT_NAME_UNIQUE;
    }

    @Override
    public Set<String> roleDeptIds(Long roleId)
    {
        return deptMapper.selectRoleDeptIds(roleId);
    }

    @Override
    public List<Map<String, Object>> selectDeptsByParentdeptid(Long parentdeptid, String childrens) {
        List<SysDept> sysDepts = new ArrayList<>();
        List<Map<String, Object>> maps = new ArrayList<>();
        if(childrens.equals("1")){
            sysDepts = deptMapper.selectDeptsByParentdeptid(parentdeptid);

            maps = sysDepts.stream().filter(sd -> !sd.getDeptId().equals(2l)).map(sd -> {
                Map<String, Object> map = new HashMap<>();
                map.put("id", sd.getDeptId());
                map.put("orderNum", sd.getOrderNum());
                map.put("deptName", sd.getDeptName());
                map.put("parentId", sd.getParentId());
                if (sd.getChildrens() == null) {
                    map.put("childrens", "0");
                } else {
                    map.put("childrens", "1");
                }
                return map;
            }).collect(Collectors.toList());
        }else{
            List<SysUser> sysUsers = sysUserMapper.selectUsersBydeptId(parentdeptid);
            maps  = sysUsers.stream().map(su -> {
                Map<String, Object> map = new HashMap<>();
                map.put("id", su.getUserId());
                map.put("orderNum", 0);
                map.put("parentId", parentdeptid);
                map.put("deptName", su.getUserName());
                map.put("childrens", "2");
                return map;
            }).collect(Collectors.toList());
        }

        return maps;
    }

    @Override
    public List<Map<String, Object>> selectVerifyDeptsByParentdeptid(Long parentdeptid, String childrens,boolean ifemail) {
        List<SysDept> sysDepts = new ArrayList<>();
        List<Map<String, Object>> maps = new ArrayList<>();
        if(childrens.equals("1")){
            sysDepts = deptMapper.selectDeptsByParentdeptid(parentdeptid);
            List<SysDept> collect = sysDepts.stream().filter(sd -> !sd.getDeptId().equals(2l)).collect(Collectors.toList());
            if(ifemail==true){
                collect = collect.stream().filter(c -> "0".equals(c.getStatus())).collect(Collectors.toList());
            }
            maps = collect.stream().map(sd -> {
                Map<String, Object> map = new HashMap<>();
                map.put("id", sd.getDeptId());
                map.put("orderNum", sd.getOrderNum());
                map.put("deptName", sd.getDeptName());
                map.put("parentId", sd.getParentId());
                if (sd.getChildrens() == null) {
                    map.put("childrens", "0");
                } else {
                    map.put("childrens", "1");
                }
                return map;
            }).collect(Collectors.toList());
        }else{
            List<SysUser> sysUsers = sysUserMapper.selectVerifyMembersBydeptId(parentdeptid);
            maps  = sysUsers.stream().map(su -> {
                Map<String, Object> map = new HashMap<>();
                map.put("id", su.getUserId());
                map.put("orderNum", 0);
                map.put("parentId", parentdeptid);
                if(StringUtils.isEmpty(su.getGoodrange())){
                    su.setGoodrange("无");
                }
                map.put("deptName", su.getUserName()+"-"+su.getJobnumber()+"-"+su.getGoodrange());
                map.put("childrens", "2");
                return map;
            }).collect(Collectors.toList());
        }

        return maps;
    }


    /**
     * 根据父节点的ID获取所有子节点
     *
     * @param list 分类表
     * @param parentId 传入的父节点ID
     * @return String
     */
    public List<SysDept> getChildPerms(List<SysDept> list, int parentId)
    {
        List<SysDept> returnList = new ArrayList<SysDept>();
        for (Iterator<SysDept> iterator = list.iterator(); iterator.hasNext();)
        {
        	SysDept t = (SysDept) iterator.next();
            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (t.getParentId() == parentId)
            {
                recursionFn(list, t);
                returnList.add(t);
            }
        }
        return returnList;
    }

    /**
     * 根据父节点的ID获取所有子节点 新 2020/11/2
     *
     * @param list 分类表
     * @param parentId 传入的父节点ID
     * @return String
     */
    public List<SysDept> getChildPermsNew(List<SysDept> list, int parentId)
    {
        List<SysDept> returnList = new ArrayList<SysDept>();
        for (Iterator<SysDept> iterator = list.iterator(); iterator.hasNext();)
        {
            SysDept t = (SysDept) iterator.next();
            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (t.getParentId() == parentId)
            {
                recursionFnNew(list, t);
                returnList.add(t);
            }
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     * @param list
     * @param t
     */
    private void recursionFn(List<SysDept> list, SysDept t)
    {
        // 得到子节点列表
        List<SysDept> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysDept tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                // 判断是否有子节点
                Iterator<SysDept> it = childList.iterator();
                while (it.hasNext())
                {
                	SysDept n = (SysDept) it.next();
                    recursionFn(list, n);
                }
            }
        }
    }

    /**
     * 递归列表 新 2020/11/2
     *
     * @param list
     * @param t
     */
    private void recursionFnNew(List<SysDept> list, SysDept t)
    {
        // 得到子节点列表
        List<SysDept> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysDept tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                // 判断是否有子节点
                t.setChildrens("1");
                Iterator<SysDept> it = childList.iterator();
                while (it.hasNext())
                {
                    SysDept n = (SysDept) it.next();
                    recursionFnNew(list, n);
                }
            }else{
                t.setChildrens("0");
            }
        }
    }

    /**
     * 递归列表 新 2020/11/3
     *
     * @param list
     * @param
     */
    private void recursionFnReverse(List<SysDept> list, List<SysDept> userlist,List<SysDept> hassonlist)
    {
        // 得到子节点列表
        hassonlist.addAll(userlist);
//        if(userlist.size()==0){
//            return ;
//        }
        if(userlist.size()!=0) {
//            List<SysDept> parentdepts = userlist.stream().map(u -> getParent(list, u)
//            ).filter(distinctByKey(u -> u.getId())).filter(d -> !d.getId().equals(1l)).collect(Collectors.toList());
            List<SysDept> parentdepts = userlist.stream().map(u -> getParent(list, u)
            ).filter(u -> u!=null).filter(distinctByKey(u -> u.getId())).filter(d -> !d.getId().equals(2l)).collect(Collectors.toList());

            recursionFnReverse(list, parentdepts, hassonlist);
        }


    }

    /**
     * 得到子节点列表
     */
    private List<SysDept> getChildList(List<SysDept> list, SysDept t)
    {
        List<SysDept> tlist = new ArrayList<SysDept>();
        Iterator<SysDept> it = list.iterator();
        while (it.hasNext())
        {
        	SysDept n = (SysDept) it.next();
            if (n.getParentId().longValue() == t.getDeptId().longValue())
            {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 得到子节点列表
     */
    private SysDept getParent(List<SysDept> list, SysDept t)
    {
//        List<SysDept> collect = list.stream().filter(l -> !"-1".equals(l.getDeptId().toString())).collect(Collectors.toList());
        Iterator<SysDept> it = list.iterator();
        while (it.hasNext())
        {
            SysDept n = (SysDept) it.next();
            if (n.getDeptId().longValue() == t.getParentId().longValue())
            {
                n.setOpen(true);
                n.setChildrens("1");
                return n;
            }
        }
        return null;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysDept> list, SysDept t)
    {
        return getChildList(list, t).size() > 0 ? true : false;
    }


    public <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }
}
